// SPDX-FileCopyrightText: 2023-2025 Sangfor Technologies Inc.
// SPDX-License-Identifier: Mulan PSL v2
package handler

import (
	"net/url"

	"code.geniusai.org/notebook-manager/pkg/config"
	"code.geniusai.org/notebook-manager/pkg/entity"
	"code.geniusai.org/notebook-manager/pkg/log"
	"code.geniusai.org/notebook-manager/pkg/resource"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
)

type MonitorHandler struct {
	resourceManager *resource.Manager
	confData        *config.Conf
}

type PrometheusConf struct {
	Url  string `yaml:"url"`
	Port string `yaml:"port"`
}

func NewMonitorHandler(resourceManager *resource.Manager, confData *config.Conf) *MonitorHandler {
	return &MonitorHandler{resourceManager, confData}
}

func (n *MonitorHandler) ShowCpuUsage(c *gin.Context) error {

	monitorReq := &entity.MonitorReq{}
	err := c.ShouldBindBodyWith(monitorReq, binding.JSON)
	if err != nil {
		log.Errorf("params invalid: %v", err)
		return err
	}

	conf := n.confData
	graphUrl := "http://" + conf.Prometheus.Url + ":" + conf.Prometheus.Port + "/api/v1/query_range?"
	pointUrl := "http://" + conf.Prometheus.Url + ":" + conf.Prometheus.Port + "/api/v1/query?"

	graphParams := url.Values{}
	graphParams.Add("query", "sum(irate(container_cpu_usage_seconds_total{namespace="+"\"%s"+"\",container=~"+"\"%s"+"-.*"+"\",pod=~"+"\"%s"+"-.*\"}[5m]))by(pod)")

	pointParams := url.Values{}
	pointParams.Add("query", "sum(irate(container_cpu_usage_seconds_total"+
		"{namespace="+"\"%s"+"\",container=~"+"\"%s"+"-.*"+"\",pod=~"+"\"%s"+"-.*\"}"+
		"[5m])*100)by(pod)/sum(container_spec_cpu_quota"+
		"{namespace="+"\"%s"+"\",container=~"+"\"%s"+"-.*"+"\",pod=~"+"\"%s"+"-.*\"}"+
		"/container_spec_cpu_period"+
		"{namespace="+"\"%s"+"\",container=~"+"\"%s"+"-.*"+"\",pod=~"+"\"%s"+"-.*\"}"+
		")by(pod)")

	monitorReq.GraphUrl = graphUrl
	monitorReq.PointUrl = pointUrl
	monitorReq.GraphParams = graphParams
	monitorReq.PointParams = pointParams

	cpuUsageData, err := n.resourceManager.GetUsage(monitorReq, "cpu")
	success(c, cpuUsageData)
	return nil
}

func (n *MonitorHandler) ShowMemoryUsage(c *gin.Context) error {
	monitorReq := &entity.MonitorReq{}
	err := c.ShouldBindBodyWith(monitorReq, binding.JSON)
	if err != nil {
		log.Errorf("params invalid: %v", err)
		return err
	}

	conf := n.confData
	graphUrl := "http://" + conf.Prometheus.Url + ":" + conf.Prometheus.Port + "/api/v1/query_range?"
	pointUrl := "http://" + conf.Prometheus.Url + ":" + conf.Prometheus.Port + "/api/v1/query?"

	graphParams := url.Values{}
	graphParams.Add("query", "sum(container_memory_working_set_bytes{namespace="+"\"%s"+"\",container=~"+"\"%s"+"-.*"+"\",pod=~"+"\"%s"+"-.*\"}/1024/1024/1024)")

	pointParams := url.Values{}
	pointParams.Add("query", "sum(container_memory_working_set_bytes{namespace="+"\"%s"+"\",container=~"+"\"%s"+"-.*"+"\",pod=~"+"\"%s"+"-.*\"}/1024/1024/1024)")

	monitorReq.GraphUrl = graphUrl
	monitorReq.PointUrl = pointUrl
	monitorReq.GraphParams = graphParams
	monitorReq.PointParams = pointParams

	memoryUsageData, err := n.resourceManager.GetUsage(monitorReq, "memory")

	success(c, memoryUsageData)
	return nil
}

func (n *MonitorHandler) ShowVGpuUsage(c *gin.Context) error {
	monitorReq := &entity.MonitorReq{}
	err := c.ShouldBindBodyWith(monitorReq, binding.JSON)
	if err != nil {
		log.Errorf("params invalid: %v", err)
		return err
	}

	conf := n.confData

	graphUrl := "http://" + conf.OrionUi.Url + ":" + conf.OrionUi.Port + "/api/v1/query_range?"
	pointUrl := "http://" + conf.OrionUi.Url + ":" + conf.OrionUi.Port + "/api/v1/query?"

	graphParams := url.Values{}
	graphParams.Add("query", "sum(avg by (pindex,vindex,host_ip) (ORIONX_VGPU_MEMORY_USAGE{group_id="+"\"%s-%s"+"\"}))/1024 or vector(0)")

	pointParams := url.Values{}
	pointParams.Add("query", "sum(avg by (pindex,vindex,host_ip) (ORIONX_VGPU_MEMORY_USAGE{group_id="+"\"%s-%s"+"\"}))/1024 or vector(0)")

	monitorReq.GraphUrl = graphUrl
	monitorReq.PointUrl = pointUrl
	monitorReq.GraphParams = graphParams
	monitorReq.PointParams = pointParams

	vGpuUsageData, err := n.resourceManager.GetUsage(monitorReq, "vGpu")

	success(c, vGpuUsageData)
	return nil
}

func (n *MonitorHandler) ShowRatioUsage(c *gin.Context) error {
	monitorReq := &entity.MonitorReq{}
	err := c.ShouldBindBodyWith(monitorReq, binding.JSON)
	if err != nil {
		log.Errorf("params invalid: %v", err)
		return err
	}

	conf := n.confData

	graphUrl := "http://" + conf.OrionUi.Url + ":" + conf.OrionUi.Port + "/api/v1/query_range?"
	pointUrl := "http://" + conf.OrionUi.Url + ":" + conf.OrionUi.Port + "/api/v1/query?"

	graphParams := url.Values{}
	graphParams.Add("query", "sum(avg by (pindex,vindex,host_ip) (ORIONX_VGPU_UTILIZATION{group_id="+"\"%s-%s"+"\"})) or vector(0)")

	pointParams := url.Values{}
	pointParams.Add("query", "sum(avg by (pindex,vindex,host_ip) (ORIONX_VGPU_UTILIZATION{group_id="+"\"%s-%s"+"\"})) or vector(0)")

	monitorReq.GraphUrl = graphUrl
	monitorReq.PointUrl = pointUrl
	monitorReq.GraphParams = graphParams
	monitorReq.PointParams = pointParams

	vGpuUsageData, err := n.resourceManager.GetUsage(monitorReq, "ratio")

	success(c, vGpuUsageData)
	return nil
}

func (n *MonitorHandler) ShowPvcUsage(c *gin.Context) error {
	monitorReq := &entity.MonitorReq{}
	err := c.ShouldBindBodyWith(monitorReq, binding.JSON)
	if err != nil {
		log.Errorf("params invalid: %v", err)
		return err
	}

	conf := n.confData

	pointUrl := "http://" + conf.StatPvc.Url + ":" + conf.StatPvc.Port + "/stat-pvc"
	monitorReq.PointUrl = pointUrl
	vGpuUsageData, err := n.resourceManager.GetPvcUsage(monitorReq)

	success(c, vGpuUsageData)
	return nil
}
